
const puppeteer = require("puppeteer");
const dayjs = require("dayjs");
const axios = require("axios");
const userDataDir = process.env.WEB_CONFIG_BAIJIAHAO_DATA_DIR;
const executablePath = process.env.WEB_CONFIG_EXECUTABLE_PATH;
const BAIJIAHAO_USERNAME = process.env.BAIJIAHAO_USERNAME;
const BAIJIAHAO_PASSWORD = process.env.BAIJIAHAO_PASSWORD;
const userAgent = process.env.USER_AGENT;
const logger = require("../../utils/logger");
const fs = require("fs");
const path = require("path");
const { promisify } = require("util");
const stream = require("stream");
const pipeline = promisify(stream.pipeline);
const { publishCallback } = require("../../utils");

async function getArticlesInfo(params) {
  let results = [];
  const browser = await puppeteer.launch({
    headless: false,
    userDataDir,
    executablePath,
    defaultViewport: null,
    args: [
      "--no-sandbox",
      "--disable-setuid-sandbox",
      "--disable-features=site-per-process",
      "--start-maximized",
    ],
    ignoreHTTPSErrors: true,
  });
  try {
    const page = await browser.newPage();
    await page.setUserAgent(userAgent);
    // 获取浏览器窗口的实际尺寸
    const dimensions = await page.evaluate(() => {
      return {
        width: window.innerWidth,
        height: window.innerHeight,
      };
    });
    logger.info("浏览器窗口实际大小: " + JSON.stringify(dimensions, null, 2));
    // 设置页面视口为浏览器窗口的实际尺寸
    await page.setViewport(dimensions);
    await page.goto("https://baijiahao.baidu.com/builder/rc/home", {
      waitUntil: "networkidle2",
    });
    if (await isNotLogin(page)) {
      logger.info("未登录，等待用户登录...");
      await page.evaluate(() => {
        const loginButton = document.querySelector("div[class*='btnlogin-']");
        if (loginButton) {
          loginButton.click();
        }
      });
      await new Promise((resolve) => setTimeout(resolve, 1500));
      await page.evaluate(() => {
        const isAgreeCheckbox = document.querySelector("input[name='isAgree']");
        if (isAgreeCheckbox) {
          isAgreeCheckbox.click();
        }
      });
      // 输入用户名
      await page.type("input[name='userName']", BAIJIAHAO_USERNAME);
      await new Promise((resolve) => setTimeout(resolve, 1500));

      // 输入密码
      await page.type("input[name='password']", BAIJIAHAO_PASSWORD);
      await new Promise((resolve) => setTimeout(resolve, 1500));

      // 点击登录按钮
      await page.click("input[type='submit']");

      // 等待登录完成
      await page.waitForNavigation({
        waitUntil: "networkidle2",
        timeout: 600000,
      });

      logger.info("登录成功");
    }
    logger.info("已登录");
    // 拦截一下请求地址是：https://baijiahao.baidu.com/pcui/article/lists?currentPage=1&pageSize=10&search=&type=&collection=&dynamic=1 的get请求，获取url参数
    const interceptPromise = new Promise((resolve, reject) => {
      page.on("request", async (interceptedRequest) => {
        const url = interceptedRequest.url();
        if (url.includes("https://baijiahao.baidu.com/pcui/article/lists")) {
          const method = interceptedRequest.method();
          const headers = interceptedRequest.headers();
          const urlParams = new URLSearchParams(url);

          if (method === "GET" && urlParams) {
            // 设置日期范围
            let startDate = setStartDate(params);

            // 初始化分页参数
            let currentPage = 1;
            let totalPage = 1;
            let shouldContinue = true;

            do {
              urlParams.set("currentPage", currentPage);

              try {
                const response = await axios({
                  url: url,
                  method: "GET",
                  headers: headers,
                  params: Object.fromEntries(urlParams.entries()),
                });

                if (
                  response.status >= 200 &&
                  response.status < 300 &&
                  response.data.errno === 0
                ) {
                  logger.info(
                    `请求成功: 第${currentPage}页 - 共${response.data.data.list.length}条`
                  );

                  const filteredResults = filterAndFormatResults(
                    response.data.data.list,
                    startDate
                  );

                  // 检查是否所有结果都被过滤掉了
                  if (filteredResults.length === 0) {
                    logger.info("没有找到符合日期条件的文章，停止请求。");
                    shouldContinue = false;
                    break;
                  }

                  results = results.concat(filteredResults);

                  // 更新分页信息
                  currentPage = response.data.data.page.currentPage + 1;
                  totalPage = response.data.data.page.totalPage;
                } else {
                  logger.error(
                    `请求失败: ${response.data.errmsg || response.statusText}`
                  );
                  break;
                }
              } catch (error) {
                logger.error(`请求发生错误: ${error.message}`);
                break;
              }

              // 添加5秒延迟
              await new Promise((resolve) => setTimeout(resolve, 5000));
            } while (currentPage <= totalPage && shouldContinue);

            resolve(); // 所有页面处理完毕后解析Promise
            interceptedRequest.abort();
          } else {
            interceptedRequest.continue();
          }
        } else {
          interceptedRequest.continue();
        }
      });
    });

    await page.setRequestInterception(true);

    try {
      await page.waitForSelector("#asideMenuItem-内容管理", {
        timeout: 10000,
      });
      await new Promise((resolve) => setTimeout(resolve, 1500));
      await page.click("#asideMenuItem-内容管理");
      logger.info("点击了内容管理");
      await page.waitForSelector("#asideMenuItem-作品管理", {
        timeout: 10000,
      });
      await new Promise((resolve) => setTimeout(resolve, 1500));
      await page.click("#asideMenuItem-作品管理");
      logger.info("文旅百家号点击了作品管理");
    } catch (error) {
      // 2024-10-22 改版 等待元素出现(个人的和文旅号的页面结构不一样)
      await page.evaluate(() => {
        const link = Array.from(
          document.querySelectorAll("ul[data-label='manage'] a")
        ).find((a) => a.textContent.includes("内容管理"));
        if (link) {
          link.click();
          console.log("通过 JavaScript 点击了 '内容管理' 链接");
        } else {
          console.warn("在 JavaScript 中未找到 '内容管理' 链接");
        }
      });
      logger.info("个人百家号点击内容管理");
    }
    // 再次等待导航完成
    await page.waitForNavigation({ waitUntil: "networkidle2" });

    // 等待拦截 Promise 完成
    await interceptPromise;
    return results;
  } catch (error) {
    logger.error(`发生错误: ${error.message}`);
    return [];
  } finally {
    await browser.close();
  }
}

// 辅助函数: 检查是否登录
async function isNotLogin(page) {
  try {
    // 2024-10-22 改版 .cms-aside-selector 改成了 #layout-main-content
    await page.waitForSelector("#layout-main-content", { timeout: 60000 });
    return false;
  } catch (error) {
    return true;
  }
}

// 添加 setStartDate 函数定义
function setStartDate(params) {
  if (params.update_type === "highFrequency") {
    return dayjs().subtract(7, "day");
  } else if (params.interval) {
    return dayjs().subtract(parseInt(params.interval), "day");
  } else {
    // 默认获取2024年的数据
    return dayjs("2024-01-01");
  }
}

// filterAndFormatResults 函数定义（如果还没有的话）
function filterAndFormatResults(list, startDate) {
  const startDateMoment = dayjs(startDate);
  const endDateMoment = dayjs();

  return list
    .filter((item) => {
      const commitAtMoment = dayjs(item.publish_time);
      return (
        (commitAtMoment.isAfter(startDateMoment) ||
          commitAtMoment.isSame(startDateMoment)) &&
        commitAtMoment.isBefore(endDateMoment)
      );
    })
    .map((item) => ({
      title: item.title,
      cover: JSON.stringify([JSON.parse(item.cover_images)[0]?.src || ""]),
      url: item.url,
      id: item.id,
      publish_time: dayjs(item.publish_time).format("YYYY-MM-DD HH:mm:ss"),
      recommend_count: item.rec_amount,
      read_count: item.read_amount,
      comment_count: item.comment_amount,
      like_count: item.like_amount,
      collect_count: item.collection_amount,
      share_count: item.share_amount,
    }));
}
//------------------------------------------------------- 百家号发布开始 -------------------------------------------------------
async function publish(params) {
  const browser = await puppeteer.launch({
    headless: false,
    userDataDir,
    executablePath,
    defaultViewport: null,
    args: [
      "--no-sandbox",
      "--disable-setuid-sandbox",
      "--disable-features=site-per-process",
      "--start-maximized",
    ],
    ignoreHTTPSErrors: true,
  });

  try {
    const page = await browser.newPage();
    await page.setUserAgent(userAgent);
    // 获取浏览器窗口的实际尺寸
    const dimensions = await page.evaluate(() => {
      return {
        width: window.innerWidth,
        height: window.innerHeight,
      };
    });
    logger.info("浏览器窗口实际大小: " + JSON.stringify(dimensions, null, 2));
    // 设置页面视口为浏览器窗口的实际尺寸
    await page.setViewport(dimensions);
    await page.goto("https://baijiahao.baidu.com/builder/rc/home", {
      waitUntil: "networkidle2",
    });
    if (await isNotLogin(page)) {
      logger.info("未登录，等待用户登录...");
      await page.evaluate(() => {
        const loginButton = document.querySelector("div[class*='btnlogin-']");
        if (loginButton) {
          loginButton.click();
        }
      });
      await new Promise((resolve) => setTimeout(resolve, 1500));
      await page.evaluate(() => {
        const isAgreeCheckbox = document.querySelector("input[name='isAgree']");
        if (isAgreeCheckbox) {
          isAgreeCheckbox.click();
        }
      });
      // 输入用户名
      await page.type("input[name='userName']", BAIJIAHAO_USERNAME);
      await new Promise((resolve) => setTimeout(resolve, 1500));

      // 输入密码
      await page.type("input[name='password']", BAIJIAHAO_PASSWORD);
      await new Promise((resolve) => setTimeout(resolve, 1500));

      // 点击登录按钮
      await page.click("input[type='submit']");

      // 等待登录完成
      await page.waitForNavigation({
        waitUntil: "networkidle2",
        timeout: 600000,
      });

      logger.info("登录成功");
    }
    logger.info("已登录");
    await page.goto(
      "https://baijiahao.baidu.com/builder/rc/edit?type=videoV2&is_from_cms=1",
      {
        waitUntil: "networkidle2",
      }
    );
    logger.info("已进入视频发布页面");

    // 下载视频文件
    await downloadFiles(params);
    // 如果有上一次缓存的视频就删除
    await page.evaluate(() => {
      const videoInput = document.querySelector(".cover-item-del");
      if (videoInput) {
        videoInput.click();
      }
    });
    await new Promise((resolve) => setTimeout(resolve, 3000));
    // 删除确认弹窗
    await page.evaluate(() => {
      const allBtns = document.querySelectorAll(".cheetah-modal-wrap button");
      Array.from(allBtns).forEach((btn) => {
        if (btn.textContent.includes("确 定")) {
          btn.click();
        } else if (btn.textContent.includes("确")) {
          btn.click();
        }
      });
    });
    // 等待视频上传完成
    await new Promise((resolve) => setTimeout(resolve, 2000));

    // 上传视频文件
    await uploadFiles(page, params);

    // 输入标题
    logger.info(`开始输入标题: ${params.title}`);
    // 点三次删除
    await page.click(".client_pages_edit_components_titleInput textarea", {
      clickCount: 3,
    });
    await new Promise((resolve) => setTimeout(resolve, 1000));
    await page.keyboard.press("Backspace");
    await page.type(
      ".client_pages_edit_components_titleInput textarea",
      params.title,
      { delay: 100 }
    );

    // 输入话题
    logger.info(`开始输入话题: ${params.talk}`);
    await handleTopics(page, params.talk);
    await new Promise((resolve) => setTimeout(resolve, 2000));
    // 选择分类下拉框
    await handleCategories(page, params.categories);

    // 选择设置
    logger.info(`开始选择设置: ${params.setting}`);
    await handleSettings(page, params.setting);
    // 输入标签 tags
    // logger.info(`开始输入标签: ${params.tags}`);
    // await handleTags(page, params.tags);
    // 清空简介
    logger.info(`开始清空简介`);
    // 点三次删除
    await page.click(".video-desc textarea", { clickCount: 3 });
    await new Promise((resolve) => setTimeout(resolve, 1000));
    await page.keyboard.press("Backspace");

    // 点击发布按钮
    await page.click("#new-operator-content .cheetah-public button");
    // 等待发布完成
    const response = await page.waitForResponse((response) =>
      response
        .url()
        .includes("https://baijiahao.baidu.com/pcui/article/publish")
    );
    // 获取 响应数据 ret 里面的 id
    const data = await response.json();
    const id = data.ret.id;
    logger.info(`发布成功，id: ${id}`);
    logger.info("视频发布成功");
    return {
      success: true,
      message: "发布成功",
      id,
    };
  } catch (error) {
    logger.error(`发布视频时发生错误: ${error.message}`);
    return {
      success: false,
      message: "发布失败: " + error.message,
    };
  } finally {
    await browser.close();
  }
}

async function downloadFiles(params) {
  logger.info(`开始下载文件，标题：${params.title}`);
  const date = dayjs().format("YYYY-MM-DD");
  const dir = path.join(__dirname, `../uploads/baijiahao/${date}`);
  if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir, { recursive: true });
  }

  if (params.video) {
    logger.info(`开始下载视频: ${params.video}`);
    const videoName = path.basename(new URL(params.video).pathname);
    const videoPath = path.join(dir, videoName);
    await downloadFile(params.video, videoPath);
    params.video = videoPath;
    logger.info(`视频下载成功，地址：${videoPath}`);
  }

  if (params.cover) {
    logger.info(`开始下载封面: ${params.cover}`);
    const coverName = path.basename(new URL(params.cover).pathname);
    const coverPath = path.join(dir, coverName);
    await downloadFile(params.cover, coverPath);
    params.cover = coverPath;
    logger.info(`封面下载成功，地址：${coverPath}`);
  }

  logger.info(`所有文件下载完成`);
}

async function downloadFile(fileUrl, localPath) {
  const response = await axios({
    method: "GET",
    url: fileUrl,
    responseType: "stream",
  });

  await pipeline(response.data, fs.createWriteStream(localPath));
}

async function uploadFiles(page, params) {
  logger.info(`开始上传文件，标题：${params.title}`);

  try {
    // 上传视频
    const videoInput = await page.$(
      '.video-wrap input[type="file"][accept*="mp4"]'
    );
    await videoInput.uploadFile(params.video);

    // 等待视频上传完成, 最长等待15分钟
    await page.waitForResponse(
      (response) =>
        response
          .url()
          .includes(
            "https://baijiahao.baidu.com/materialui/video/compuploadvideo"
          ),
      { timeout: 600000 }
    );
    logger.info("视频上传成功");

    // 上传封面（如果有）
    if (params.cover) {
      // 上传竖屏封面
      await uploadCover(page, params.cover, 0, "竖屏");
      await new Promise((resolve) => setTimeout(resolve, 3000));
      // 上传横屏封面
      await uploadCover(page, params.cover, 1, "横屏");
    }

    logger.info("所有文件上传完成");
  } catch (error) {
    logger.error(`上传文件时发生错误: ${error.message}`);
    throw error;
  }
}

async function uploadCover(page, coverPath, index, orientation) {
  try {
    // 点击编辑按钮
    // const editButtons = await page.$$(".actions-wrap>span:nth-child(2)");
    // await editButtons[index].click();
    await page.evaluate((idx) => {
      const editButtons = document.querySelectorAll(
        ".actions-wrap>span:nth-child(2)"
      );
      const _editButtons = document.querySelectorAll(
        ".video-v2-placehold-wrap>.video-v2-btn:nth-child(1)"
      );
      console.log("editButtons", editButtons);
      console.log("_editButtons", _editButtons);
      Array.from(editButtons).forEach((btn, i) => {
        if (idx === i) {
          btn.click();
        }
      });
      Array.from(_editButtons).forEach((btn, i) => {
        if (i === 0) {
          btn.click();
        }
      });
    }, index);

    // 等待弹窗出现
    await new Promise((resolve) => setTimeout(resolve, 3000));
    logger.info("弹窗出现");
    await page.evaluate(() => {
      const uploadButton = document.querySelector(
        "div[data-node-key='choose']"
      );
      if (uploadButton) {
        uploadButton.click();
      }
    });
    await new Promise((resolve) => setTimeout(resolve, 1500));
    // 上传文件
    const fileInput = await page.$(
      '.cheetah-upload input[type="file"][accept*="image"]'
    );
    await fileInput.uploadFile(coverPath);
    // 等待上传成功
    await page.waitForResponse(
      (response) =>
        response
          .url()
          .includes(
            "https://baijiahao.baidu.com/materialui/picture/uploadProxy"
          ),
      { timeout: 60000 }
    );
    await new Promise((resolve) => setTimeout(resolve, 3000));
    // 点击确认按钮
    await page.evaluate(() => {
      const allBtns = document.querySelectorAll(".cheetah-modal-wrap button");
      Array.from(allBtns).forEach((btn) => {
        if (btn.textContent.includes("确 认")) {
          btn.click();
        } else if (btn.textContent.includes("确")) {
          btn.click();
        }
      });
    });

    // 等待弹窗消失
    await page.waitForSelector(".cheetah-modal-wrap", { hidden: true });
    await page.waitForResponse(
      (response) =>
        response
          .url()
          .includes("https://baijiahao.baidu.com/pcui/Brain/CoordRcmd"),
      { timeout: 60000 }
    );
    logger.info(`${orientation}封面上传成功`);
  } catch (error) {
    logger.error(`上传${orientation}封面时发生错误: ${error.message}`);
    throw error;
  }
}

async function handleTopics(page, topics) {
  logger.info(`开始添加话题: ${topics}`);
  if (!topics || topics.length === 0) {
    logger.info("没有话题");
    return;
  }
  for (const topic of topics) {
    // focus
    await page.focus(".edit-video-topic-input");
    await page.keyboard.press("Backspace");
    await page.type(".edit-video-topic-input", topic, { delay: 100 });
    await new Promise((resolve) => setTimeout(resolve, 5000));
    await page.evaluate((t) => {
      const topicItem = document.querySelectorAll(".topic-list .topic-text");
      console.log("topicItem", topicItem);
      Array.from(topicItem).forEach((item) => {
        if (item.textContent === t) {
          item.click();
        }
      });
    }, topic);
    await new Promise((resolve) => setTimeout(resolve, 1000));
  }
  logger.info(`已添加话题: ${topics.join(", ")}`);
}
//
async function handleSettings(page, setting) {
  logger.info(`开始设置: ${setting}`);
  // 取消所有选中
  await page.evaluate(() => {
    const allCheckbox = document.querySelectorAll(
      ".pages_videoV2_formModule_components_setting_index .cheetah-checkbox-input"
    );
    Array.from(allCheckbox).forEach((item) => {
      if (item.checked) {
        item.click();
      }
    });
  });
  if (!setting || setting.length === 0) {
    logger.info("没有设置");
    return;
  }
  await new Promise((resolve) => setTimeout(resolve, 1000));
  // 选择设置
  await page.evaluate((settings) => {
    const settingItem = document.querySelectorAll(
      ".pages_videoV2_formModule_components_setting_index .cheetah-checkbox-input"
    );
    Array.from(settingItem).forEach((item, index) => {
      for (const currentSetting of settings) {
        if (index === currentSetting) {
          item.click();
        }
      }
    });
  }, setting);
}
// 输入标签
async function handleTags(page, tags) {
  logger.info(`开始输入标签: ${tags}`);
  if (!tags || tags.length === 0) {
    logger.info("没有标签");
    return;
  }
  for (const tag of tags) {
    await page.type(".cheetah-ui-pro-tag-input-container-tag-input", tag, {
      delay: 100,
    });
    //回车
    await page.keyboard.press("Enter");
    await new Promise((resolve) => setTimeout(resolve, 1000));
    logger.info(`已添加标签: ${tag}`);
  }
}
// 设置分类
// "categories":["军事","军事历史"],
async function handleCategories(page, cates) {
  // 点击打开分类选择器
  if (!cates || cates.length === 0) {
    logger.info("没有分类");
    return;
  }
  await page.evaluate(() => {
    const selectors = document.querySelectorAll(".cheetah-select-selector");
    Array.from(selectors).forEach((selector) => {
      if (selector.textContent.includes("分类")) {
        selector.click();
        selector.dispatchEvent(new Event("click", { bubbles: true }));
        selector.dispatchEvent(new Event("mousedown", { bubbles: true }));
      }
    });
  });
  await new Promise((resolve) => setTimeout(resolve, 1000));
  // 等待下拉菜单加载
  await page.waitForSelector(".cheetah-cascader-dropdown", { visible: true });

  // 依次选择每个分类
  for (let i = 0; i < cates.length; i++) {
    const category = cates[i];

    await page.evaluate((cat) => {
      const menuItems = document.querySelectorAll(
        ".cheetah-cascader-menu:last-child .cheetah-cascader-menu-item-content"
      );
      for (const item of menuItems) {
        if (item.textContent.trim() === cat) {
          item.click();
          return;
        }
      }
    }, category);

    // 等待下一级菜单加载（如果有的话）
    if (i < cates.length - 1) {
      await page.waitForFunction(
        (index) =>
          document.querySelectorAll(".cheetah-cascader-menu").length > index,
        {},
        i + 1
      );
    }

    // 短暂等待，确保UI更新
    await new Promise((resolve) => setTimeout(resolve, 1000));
  }

  // 记录日志
  logger.info(`已选择分类: ${cates.join(" > ")}`);
}
//------------------------------------------------------- 百家号发布结束 -------------------------------------------------------
exports.handleCommand = async (command, params, taskId) => {
  switch (command) {
    case "getArticlesInfo":
      const data = await getArticlesInfo(params);
      return { data };
    case "publish":
      try {
        const result = await publish(params);
        if (result.success) {
          await publishCallback(
            params.post_id,
            3,
            "发布成功",
            taskId,
            result.id
          );
          return {
            data: [
              {
                ...result,
              },
            ],
          };
        } else {
          throw new Error(result.message);
        }
      } catch (error) {
        logger.error(`发布文章时发生错误: ${error.message}`);
        await publishCallback(params.post_id, 4, error.message, taskId, "");
        return {
          data: [
            {
              success: false,
              message: error.message,
            },
          ],
        };
      }
    default:
      throw new Error("Unsupported command");
  }
};
